
Imports std
Imports System.IO

Module sortW
    Public sortBound As Int32 = 512000

    Sub Main(ByVal args() As String)
        On Error Resume Next
        Dim reader As TextReader = Nothing
        Dim writer As TextWriter = Nothing
        Dim inputs As vector(Of vector(Of String)) = Nothing
        Dim line As String = Nothing
        Dim i As Int32
        Dim j As Int32
        Dim comparer As vectorStringComparer = Nothing
        Dim factors As vector(Of String) = Nothing
        Dim temps As vector(Of String) = Nothing
        Dim clearAfter As Boolean = True
        Dim argflag As Boolean = True
        Dim mergearg As String = Nothing

        If args.Length < 3 Then
            raiseError("argument count error, [/nc<not clean temp files after sorting>]" + _
                            " [/s sortBound<" + Convert.ToString(sortBound) + " as default>] [/merge arg] " + _
                            "comparefactor0,comparefactor1, ... ,comparefactorM " + _
                            "input1 input2 ... inputN output, if input / output is '/-', use console", _
                            errorHandle.errorType.critical)
        Else
            registerConsoleExtHandle()

            i = 0
            While argflag
                argflag = False
                If strsame(args(i), "/nc", False) Then
                    clearAfter = False
                    i += 1
                    argflag = True
                ElseIf strsame(args(i), "/s", False) Then
                    sortBound = Convert.ToInt32(args(i + 1))
                    i += 2
                    argflag = True
                ElseIf strsame(args(i), "/merge", False) Then
                    mergearg = args(i + 1)
                    i += 2
                    argflag = True
                End If
            End While
            strsepar(args(i), character.comma + character.semicolon + character.sheffer + character.tab + character.blank _
                                + character.fullStop + character.leftSlash + character.rightSlash, factors)
            i += 1
            comparer = New vectorStringComparer()
            comparer.initial(factors)
            inputs = New vector(Of vector(Of String))
            temps = New vector(Of String)

            For i = i To args.Length - 2
                If args(i) = "/-" Then
                    reader = Console.In
                Else
                    reader = New StreamReader(New FileStream(args(i), FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
                End If
                assert(Not reader Is Nothing, "file no found, " + args(i))

                line = reader.ReadLine
                While Not line Is Nothing AndAlso Not consoleExtSignal()
                    If Not isemptystring(line) Then
                        inputs.push_back(New vector(Of String))
                        strsepar(line, character.tab, inputs(inputs.size() - 1))
                        If inputs.size() >= sortBound Then
                            line = createGUID()
                            Array.Sort(inputs.data, 0, inputs.size, comparer)
                            writer = New StreamWriter(New FileStream(line, FileMode.Create, FileAccess.Write, FileShare.Read))
                            assert(Not writer Is Nothing, "file no found, " + line)
                            For j = 0 To inputs.size() - 1
                                writer.WriteLine(inputs(j).ToString())
                            Next
                            closestream(writer)
                            inputs.clear()

                            temps.push_back(line)
                            destructor.destruct()
                        End If
                    End If
                    line = reader.ReadLine
                End While
                closestream(reader)
            Next

            If inputs.size() > 0 AndAlso Not consoleExtSignal() Then
                line = Guid.NewGuid().ToString()
                Array.Sort(inputs.data, 0, inputs.size, comparer)
                writer = New StreamWriter(New FileStream(line, FileMode.Create, FileAccess.Write, FileShare.Read))
                assert(Not writer Is Nothing, "file no found, " + line)
                For j = 0 To inputs.size() - 1
                    writer.WriteLine(inputs(j).ToString())
                Next
                closestream(writer)
                inputs.clear()

                temps.push_back(line)
            End If

            If Not consoleExtSignal() Then
                Dim outfilename As String = createGUID()
                line = "mergesortreduce " + mergearg
                For i = 0 To factors.size() - 1
                    line += " -s "
                    line += factors(i)
                Next
                For i = 0 To temps.size() - 1
                    line += " -i "
                    line += temps(i)
                Next
                line += " -o " + outfilename

                If args(args.Length() - 1) = "/-" Then
                    writer = Console.Out
                Else
                    writer = Nothing
                End If

                If Object.ReferenceEquals(writer, Console.Out) Then
                    line = "cmd /c " + line + " 1> nul"
                Else
                    raiseError("external function, " + line, errorHandle.errorType.application)
                End If
                Shell(line, AppWinStyle.Hide, True)

                If writer Is Nothing Then
                    If File.Exists(args(args.Length() - 1)) Then
                        Dim rtn As String = inputline("delete existing file " + args(args.Length() - 1) + "? [Yes,No]")
                        If Not (strsame(rtn, "no", False) Or strsame(rtn, "n", False)) Then
                            File.Delete(args(args.Length() - 1))
                        End If
                    End If
                    Rename(outfilename, args(args.Length() - 1))
                Else
                    reader = New StreamReader(New FileStream(outfilename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
                    line = reader.ReadLine
                    While Not line Is Nothing AndAlso Not consoleExtSignal()
                        writer.WriteLine(line)
                        line = reader.ReadLine()
                    End While
                    closestream(reader)
                    File.Delete(outfilename)
                End If
            End If
            If clearAfter Then
                For i = 0 To temps.size() - 1
                    System.IO.File.Delete(temps(i))
                Next
            End If

            consoleExtHandleFinish()
        End If
    End Sub

End Module
